import { _decorator, Component, Node, Vec2, Vec3, Quat, misc, SkeletalAnimation, Camera, find, RigidBody } from "cc";
import { VisualAngle } from "../../game/ui/Panel";
import event from "../../utils/event";
import websocket from "../../utils/websocket";
const { ccclass, property } = _decorator;

type RockerData = {
    action: "move" | "reset";
    angle: number;
    distance: number;
};

type CameraData = {
    action: "move" | "reset";
    delta: Vec2;
};

const rotateByPoint = (target: Vec3, center: Vec3, angle: number, axis: Vec3 = Vec3.UP): Vec3 => {
    let quat = new Quat();
    let dir = new Vec3();
    let rotated = new Vec3();
    // 逐元素向量减法: 目标位置 - 中心位置 = 由中心位置指向目标位置的向量
    Vec3.subtract(dir, target, center);
    // 角度转弧度
    let rad = misc.degreesToRadians(angle);
    // 根据旋转轴和旋转弧度计算四元数: 绕指定轴旋转指定弧度后的四元数
    Quat.fromAxisAngle(quat, axis, rad);
    // 向量四元数乘法: 向量 * 四元数 = 该向量按照四元数旋转后的向量
    Vec3.transformQuat(rotated, dir, quat);
    // 逐元素向量加法: 中心点 + 旋转后的向量 = 旋转后的点
    Vec3.add(rotated, center, rotated);
    return rotated;
};

@ccclass("PlayerShadow")
export class PlayerShadow extends Component {
    @property(Node)
    private role: Node = null;
    @property(Node)
    private cameraTarget: Node = null;
    @property(RigidBody)
    private rigidBody: RigidBody = null;

    private cameraNode: Node = null;
    private rocker: RockerData = { action: "reset", angle: 0, distance: 0 };
    private roleAni: SkeletalAnimation = null;
    private curAction: string = null;
    private isJump: boolean = false;
    private userInfo = null;
    private cameraDistance = 10;

    private _curPos = new Vec3();
    private _curRot = new Quat();

    start() {
        event.on("rocker", this.onRockerChange, this);
        event.on("panel.jump", this.onPlayerJump, this);
        event.on("panel.visual", this.onVisualSwitch, this);
        event.on("panel.camera", this.onPlayerViewRotate, this);
        event.on("game::userinfo", this.onUserInfo, this);
        websocket.on("game::enter", this.onGameEnter, this);

        this.roleAni = this.role.getComponent(SkeletalAnimation);
        this.cameraNode = find("Main Camera");

        this.setCamera(Vec2.ZERO);
    }

    update(deltaTime: number) {
        if (this.rocker?.action === "move") {
            let { x, y, z } = this.node.getPosition();
            const angle = this.rocker.angle + this.cameraNode.getWorldRotation().getEulerAngles(new Vec3()).y + 180;

            const r = deltaTime * 10;

            x = x + r * Math.cos(((angle + 180) * Math.PI) / 180);
            z = z + r * Math.sin((angle * Math.PI) / 180);

            // console.log("Role pos", x, z);
            this.node.setPosition(x, y, z);
            this.role.setRotationFromEuler(0, angle - 90, 0);

            websocket.send("player::sync", { action: "run", pos: { x, y, z }, euler: { x: 0, y: angle - 90, z: 0 } });

            this.setCamera(Vec2.ZERO);
        }
    }

    onUserInfo(data) {
        this.userInfo = data;
    }

    onGameEnter(data) {
        let mineData = data.find((item) => item.userId === this.userInfo.userId);

        console.log("PlayerShadow onGameEnter", mineData);

        if (mineData) {
            const { pos, euler } = mineData;
            this.node.setPosition(pos.x, pos.y, pos.z);
            this.role.setRotationFromEuler(euler.x, euler.y, euler.z);
        } else {
            this.node.setPosition(2, 2, 0);
            this.role.setRotationFromEuler(0, 0, 0);
        }
        this.setCamera(Vec2.ZERO);
    }

    setCamera(delta: Vec2) {
        // 参考 https://forum.cocos.org/t/topic/99459/3
        this.cameraNode.getWorldPosition(this._curPos);
        this.cameraNode.getWorldRotation(this._curRot);

        const dx = delta.x / 300; //dx,dy的数值越大则旋转的越快
        const dy = delta.y / 300;
        const rot = new Quat(this._curRot);
        const euler = new Vec3();
        Quat.rotateX(rot, rot, dy);
        Quat.rotateAround(rot, rot, Vec3.UNIT_Y, -dx);
        Quat.toEuler(euler, rot);
        Quat.fromEuler(rot, euler.x, euler.y, 0); // clear rotate of z

        const offset = new Vec3(0, 0, 1);
        Vec3.transformQuat(offset, offset, rot);
        Vec3.normalize(offset, offset);
        Vec3.multiplyScalar(offset, offset, this.cameraDistance); //数字10表示当前距离摄像机距离目标物体的直线距离

        //this.targetNode 是希望绕着旋转的节点  this.node 就是摄像机自己
        Vec3.add(this._curPos, this.cameraTarget.worldPosition, offset);
        this.cameraNode.setWorldPosition(this._curPos);

        this.cameraNode.lookAt(this.cameraTarget.worldPosition);
    }

    onRockerChange(data: RockerData) {
        console.log("onRockerChange", data);
        this.rocker = data;
        this.isJump = false;
        if (this.curAction === data.action) return;
        this.curAction = data.action;
        switch (data.action) {
            case "move":
                this.roleAni.play("run");
                websocket.send("player::sync", { action: "run" });
                break;
            case "reset":
                this.roleAni.play("idle");
                websocket.send("player::sync", { action: "idle" });
                break;
        }
    }

    onPlayerJump() {
        console.log("onPlayerJump", this.isJump);
        if (this.isJump) return;

        this.curAction = null;
        this.isJump = true;
        this.roleAni.play("attack");
        websocket.send("player::sync", { action: "attack" });
        this.roleAni.on(
            SkeletalAnimation.EventType.FINISHED,
            function () {
                console.log("onPlayerJump FINISHED");
                websocket.send("player::sync", { action: "idle" });
                this.onRockerChange(this.rocker);
            },
            this
        );
    }

    onPlayerViewRotate({ action, delta }: CameraData) {
        if (action === "reset") {
            return;
        }

        this.setCamera(delta);
    }

    onVisualSwitch(visual: VisualAngle) {
        this.cameraDistance = visual;
        this.setCamera(Vec2.ZERO);
    }
}
